% 
% @(#)ImmutableVector.X	1.2  4/11/88
%
export _immutableVectorObject to "Builtins"

const _immutableVectorObject == 
  immutable object _immutableVectorObject
    export of
    function of [ElementType : AbstractType] -> [result : NIMVT]
      where
	NIMVT ==	immutable type NIMVT
		  operation create [Integer] -> [NIMV]
		  operation new [RIS] -> [NIMV]
		  function getSignature -> [Signature]
		end NIMVT
	NIMV ==	immutable type NIMV
		  operation hiddenSetElement[Integer, ElementType]
		  function  getElement [Integer] -> [ElementType]
		    % get the element indexed by index, failing if index 
		    % out of range.
		  function  upperbound -> [Integer]
		    % return the highest valid index, ub.
		  function  lowerbound -> [Integer]
		    % return the lowest valid index, always 0.
		  function  getSlice [Integer, Integer] -> [NIMV]
		    % See implementation comment
		  operation catenate [a : NIMV] -> [r : NIMV]
		    % return a new vector the result of catenating the 
		    % elements of a to self
		end NIMV
	RIS ==  type RIS
		  function  getElement [Integer] -> [ElementType]
		  function  upperbound -> [Integer]
		  function  lowerbound -> [Integer]
		end RIS
	ElementType *> type T end T
      end where
      result <- 
	immutable object aNIMVT
	  export create, new, getSignature

	  function getSignature -> [result : Signature]
	    result <- NIMV
	  end getSignature

	  operation create[length : Integer] -> [result : NIMV]
	    result <-
	      immutable object aNIMV
		export getElement, hiddenSetElement, upperbound, lowerbound,
		      getSlice, catenate

		initially
		  var x : Integer <- length
		end initially

		function  getElement [index : Integer] -> [result : ElementType]
		  % get the element indexed by index, failing if index 
		  % out of range.
		  primitive 012 [result] <- [index]
		end getElement
		operation hiddenSetElement [index : Integer, e : ElementType]
		  % set the element, failing if index out of range
		  primitive 112 [] <- [index, e]
		end hiddenSetElement
		function  upperbound -> [r : Integer]
		  % return the highest valid index, ub.
		  primitive 212 [r] <- []
		end upperbound
		function  lowerbound -> [r : Integer]
		  % return the lowest valid index, always 1.
		  primitive 312 [r] <- []
		end lowerbound
		function  getSlice [i1 : Integer, length : Integer] -> [r : NIMV]
		  % return a new Vector, a, with lower bound 0, and 
		  % upper bound length-1, such that for 0 <= i < length:
		  %     self.getElement[i1+i] == a.getElement[i]
		  % fail if i1 or i1+length is out of range.
		  primitive 412 [r] <- [i1, length]
		end getSlice
		operation catenate [a : NIMV] -> [r : NIMV]
		  % return a new vector the result of catenating the 
		  % elements of a to self
		  primitive 612 [r] <- [a]
		end catenate
	      end aNIMV
	  end create
	  operation new[value : RIS] -> [r : NIMV]
	    var i	: Integer
	    var j 	: Integer
	    var limit	: Integer
	    var e	: ElementType

	    i <- value.lowerbound
	    limit <- value.upperbound
	    r <- self.create[limit - i + 1]
	    
	    j <- 0
	    loop
	      exit when i > limit
	      e <- value(i)
	      r.hiddenSetElement[j, e]
	      i <- i + 1
	      j <- j + 1
	    end loop
	  end new
	end aNIMVT
    end of
  end _immutableVectorObject
